﻿using OfficeOpenXml;
using OfficeOpenXml.Style;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Urs.Core;
using Urs.Data.Domain.Stores;
using Urs.Data.Domain.Users;
using Urs.Data.Domain.Orders;
using Urs.Data.Domain.Configuration;
using Urs.Services.Stores;
using Urs.Services.ExportImport.Help;
using Urs.Services.Localization;
using Urs.Services.Media;
using Urs.Data.Domain.Agents;
using Urs.Services.Orders;
using Urs.Services.Users;
using Urs.Services.Agents;

namespace Urs.Services.ExportImport
{
    public partial class ExportManager : IExportManager
    {
        #region Fields

        private readonly ICategoryService _categoryService;
        private readonly IBrandService _brandService;
        private readonly IGoodsService _goodsService;
        private readonly IPictureService _pictureService;
        private readonly StoreInformationSettings _storeInformationSettings;
        private readonly ILocalizationService _localizationService;
        private readonly IOrderService _orderService;
        private readonly IUserService _userService;
        private readonly IAgentService _agentService;

        #endregion

        #region Ctor

        public ExportManager(ICategoryService categoryService,
            IBrandService brandService,
            IGoodsService goodsService,
            IPictureService pictureService,
            StoreInformationSettings storeInformationSettings,
            ILocalizationService localizationService,
            IOrderService orderService,
            IUserService userService,
            IAgentService agentService)
        {
            this._categoryService = categoryService;
            this._brandService = brandService;
            this._goodsService = goodsService;
            this._pictureService = pictureService;
            this._storeInformationSettings = storeInformationSettings;
            this._localizationService = localizationService;
            this._orderService = orderService;
            this._userService = userService;
            this._agentService = agentService;
        }

        #endregion

        #region Utilities

        protected virtual void WriteCategories(XmlWriter xmlWriter, int parentCategoryId)
        {
            var categories = _categoryService.GetAllCategoriesByParentCategoryId(parentCategoryId, true);
            if (categories != null && categories.Count > 0)
            {
                foreach (var category in categories)
                {
                    xmlWriter.WriteStartElement("Category");
                    xmlWriter.WriteElementString("Id", null, category.Id.ToString());
                    xmlWriter.WriteElementString("Name", null, category.Name);
                    xmlWriter.WriteElementString("Description", null, category.Description);
                    xmlWriter.WriteElementString("ParentCategoryId", null, category.ParentCategoryId.ToString());
                    xmlWriter.WriteElementString("PictureId", null, category.PictureId.ToString());
                    xmlWriter.WriteElementString("PageSize", null, category.PageSize.ToString());
                    xmlWriter.WriteElementString("PriceRanges", null, category.PriceRanges);
                    xmlWriter.WriteElementString("ShowOnHomePage", null, category.ShowOnHomePage.ToString());
                    xmlWriter.WriteElementString("Published", null, category.Published.ToString());
                    xmlWriter.WriteElementString("Deleted", null, category.Deleted.ToString());
                    xmlWriter.WriteElementString("DisplayOrder", null, category.DisplayOrder.ToString());
                    xmlWriter.WriteElementString("CreateTime", null, category.CreateTime.ToString());
                    xmlWriter.WriteElementString("UpdateTime", null, category.UpdateTime.ToString());

                    xmlWriter.WriteStartElement("SubCategories");
                    WriteCategories(xmlWriter, category.Id);
                    xmlWriter.WriteEndElement();
                    xmlWriter.WriteEndElement();
                }
            }
        }

        #endregion

        #region Methods

        public virtual string ExportBrandsToXml(IList<Brand> brands)
        {
            var sb = new StringBuilder();
            var stringWriter = new StringWriter(sb);
            var xmlWriter = new XmlTextWriter(stringWriter);
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("Brands");
            xmlWriter.WriteAttributeString("Version", UrsVersion.CurrentVersion);

            foreach (var brand in brands)
            {
                xmlWriter.WriteStartElement("Brand");

                xmlWriter.WriteElementString("BrandId", null, brand.Id.ToString());
                xmlWriter.WriteElementString("Name", null, brand.Name);
                xmlWriter.WriteElementString("Description", null, brand.Description);
                xmlWriter.WriteElementString("PictureId", null, brand.PictureId.ToString());
                xmlWriter.WriteElementString("PageSize", null, brand.PageSize.ToString());
                xmlWriter.WriteElementString("Published", null, brand.Published.ToString());
                xmlWriter.WriteElementString("Deleted", null, brand.Deleted.ToString());
                xmlWriter.WriteElementString("DisplayOrder", null, brand.DisplayOrder.ToString());
                xmlWriter.WriteElementString("CreateTime", null, brand.CreateTime.ToString());
                xmlWriter.WriteElementString("UpdateTime", null, brand.UpdateTime.ToString());

                xmlWriter.WriteEndElement();
            }

            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndDocument();
            xmlWriter.Close();
            return stringWriter.ToString();
        }

        public virtual byte[] ExportBrandsToXlsx(IEnumerable<Brand> brands)
        {
            var properties = new[]
            {
                new PropertyByName<Brand>("Id", p => p.Id),
                new PropertyByName<Brand>("Name", p => p.Name),
                new PropertyByName<Brand>("Description", p => p.Description),
                new PropertyByName<Brand>("Picture", p => GetPictures(p.PictureId)),
                new PropertyByName<Brand>("PageSize", p => p.PageSize),
                new PropertyByName<Brand>("PriceRanges", p => p.PriceRanges),
                new PropertyByName<Brand>("Published", p => p.Published),
                new PropertyByName<Brand>("DisplayOrder", p => p.DisplayOrder)
            };

            return ExportToXlsx(properties, brands);
        }


        public virtual void ExportGoodssToXlsx(Stream stream, IList<Goods> list)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            using (var xlPackage = new ExcelPackage(stream))
            {

                var worksheet = xlPackage.Workbook.Worksheets.Add("Goodss");
                var properties = new string[]
                {
                    "商品名称",
                    "SKU",
                    "分类",
                    "品牌",
                    "简介",
                    "是否发布",
                    "是否配送",
                    "库存",
                    "价格",
                    "市场价",
                    "创建时间"
                };
                for (int i = 0; i < properties.Length; i++)
                {
                    worksheet.Cells[1, i + 1].Value = properties[i];
                    worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
                    worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
                    worksheet.Cells[1, i + 1].Style.Font.Bold = true;
                }


                int row = 2;
                foreach (var p in list)
                {
                    int col = 1;

                    worksheet.Cells[row, col].Value = p.Name;
                    col++;

                    worksheet.Cells[row, col].Value = p.Sku;
                    col++;

                    worksheet.Cells[row, col].Value = _categoryService.GetCategoryById(p.CategoryId)?.Name;
                    col++;

                    worksheet.Cells[row, col].Value = _brandService.GetById(p.BrandId)?.Name;
                    col++;

                    worksheet.Cells[row, col].Value = p.ShortDescription;
                    col++;

                    worksheet.Cells[row, col].Value = p.Published ? "是" : "否";
                    col++;

                    worksheet.Cells[row, col].Value = p.IsShipEnabled ? "是" : "否";
                    col++;

                    worksheet.Cells[row, col].Value = p.StockQuantity;
                    col++;

                    worksheet.Cells[row, col].Value = p.Price;
                    col++;

                    worksheet.Cells[row, col].Value = p.OldPrice;
                    col++;

                    worksheet.Cells[row, col].Value = p.CreateTime.ToString("yyyy-MM-dd HH:mm");
                    col++;

                    row++;

                }

                xlPackage.Workbook.Properties.Title = string.Format("{0} goods", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Author = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.Subject = string.Format("{0} goods", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Keywords = string.Format("{0} goods", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Category = "Goods";
                xlPackage.Workbook.Properties.Comments = string.Format("{0} goods", _storeInformationSettings.StoreName);

                xlPackage.Workbook.Properties.Company = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.HyperlinkBase = new Uri(_storeInformationSettings.StoreUrl);

                xlPackage.Save();
            }
        }

        public virtual void ExportOrdersToXlsx(Stream stream, IList<Order> orders)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            using (var xlPackage = new ExcelPackage(stream))
            {

                var worksheet = xlPackage.Workbook.Worksheets.Add("Orders");
                var properties = new string[]
                    {
                        "订单编号",
                        "订单总金额",
                        "订单小计",
                        "配送费",
                        "状态",
                        "商品编号",
                        "商品名称",
                        "商品单价",
                        "商品数量",
                        "微信昵称",
                        "联系人",
                        "联系电话",
                        "备注",
                        "社区名称",
                        "配送地址",
                        "创建时间",
                    };
                for (int i = 0; i < properties.Length; i++)
                {
                    worksheet.Cells[1, i + 1].Value = properties[i];
                    worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
                    worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
                    worksheet.Cells[1, i + 1].Style.Font.Bold = true;
                }


                int row = 2;
                foreach (var order in orders)
                {
                    foreach (var op in order.orderItems)
                    {
                        int col = 1;

                        worksheet.Cells[row, col].Value = order.Id;
                        col++;

                        worksheet.Cells[row, col].Value = order.OrderTotal;
                        col++;

                        worksheet.Cells[row, col].Value = op.UnitPrice * op.Quantity;
                        col++;

                        worksheet.Cells[row, col].Value = order.OrderShipping;
                        col++;

                        worksheet.Cells[row, col].Value = order.OrderStatus.GetLocalizedEnum(_localizationService);
                        col++;


                        worksheet.Cells[row, col].Value = op.GoodsId;
                        col++;

                        worksheet.Cells[row, col].Value = string.Format("{0} {1}", op.GoodsName, op.AttributeDescription);
                        col++;

                        worksheet.Cells[row, col].Value = op.UnitPrice;
                        col++;

                        worksheet.Cells[row, col].Value = op.Quantity;
                        col++;

                        worksheet.Cells[row, col].Value = order.User?.Nickname;
                        col++;

                        if (!string.IsNullOrEmpty(order.Remark))
                        {
                            var arry = order.Remark.Split("——");
                            if (arry.Count() > 0)
                            {
                                var xm = arry.FirstOrDefault(a => a.Contains("姓名: "));
                                var sj = arry.FirstOrDefault(a => a.Contains("手机号: "));
                                var bz = arry.FirstOrDefault(a => a.Contains("备注: "));

                                worksheet.Cells[row, col].Value = xm.Replace("姓名: ", "") ?? "";
                                col++;

                                worksheet.Cells[row, col].Value = sj.Replace("手机号: ", "") ?? "";
                                col++;

                                worksheet.Cells[row, col].Value = bz.Replace("备注: ", "") ?? "";
                                col++;
                            }
                            else
                            {
                                worksheet.Cells[row, col].Value = string.Empty;
                                col++;
                                worksheet.Cells[row, col].Value = string.Empty;
                                col++;
                                worksheet.Cells[row, col].Value = string.Empty;
                                col++;
                            }
                        }
                        else
                        {
                            worksheet.Cells[row, col].Value = string.Empty;
                            col++;
                            worksheet.Cells[row, col].Value = string.Empty;
                            col++;
                            worksheet.Cells[row, col].Value = string.Empty;
                            col++;
                        }

                        if (order.ShippingAddress != null)
                        {
                            var shippingAddress = order.ShippingAddress;
                            worksheet.Cells[row, col].Value = shippingAddress.Name;
                            col++;


                            worksheet.Cells[row, col].Value = string.Format("{0} {1} {2} {3}", shippingAddress.ProvinceName, shippingAddress.CityName, shippingAddress.AreaName, shippingAddress.Address1);
                            col++;
                        }
                        else
                        {
                            worksheet.Cells[row, col].Value = "";
                            col++;

                            worksheet.Cells[row, col].Value = "";
                            col++;
                        }

                        worksheet.Cells[row, col].Value = order.CreateTime.ToString("yyyy-MM-dd HH:mm");
                        col++;

                        row++;
                    }
                }
                xlPackage.Workbook.Properties.Title = string.Format("{0} {1} 订单", DateTime.Now.ToString("yyMMddHHmm"), _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Author = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.Subject = string.Format("{0} {1} 订单", DateTime.Now.ToString("yyMMddHHmm"), _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Keywords = string.Format("{0} {1} 订单", DateTime.Now.ToString("yyMMddHHmm"), _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Category = "Orders";
                xlPackage.Workbook.Properties.Comments = "优社电商技术支持";

                xlPackage.Workbook.Properties.Company = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.HyperlinkBase = new Uri(_storeInformationSettings.StoreUrl);

                xlPackage.Save();
            }
        }

        public virtual void ExportUsersToXlsx(Stream stream, IList<User> users)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            using (var xlPackage = new ExcelPackage(stream))
            {

                var worksheet = xlPackage.Workbook.Worksheets.Add("Users");
                var properties = new string[]
                    {
                        "用户编号",
                        "昵称",
                        "手机号",
                        "是否启用",
                        "性别",
                        "公司",
                        "省份",
                        "城市",
                        "区县",
                        "地址",
                        "邮编"
                    };
                for (int i = 0; i < properties.Length; i++)
                {
                    worksheet.Cells[1, i + 1].Value = properties[i];
                    worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
                    worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
                    worksheet.Cells[1, i + 1].Style.Font.Bold = true;
                }


                int row = 2;
                foreach (var user in users)
                {
                    int col = 1;

                    worksheet.Cells[row, col].Value = user.Id;
                    col++;

                    worksheet.Cells[row, col].Value = user.Nickname;
                    col++;

                    worksheet.Cells[row, col].Value = user.PhoneNumber;
                    col++;

                    worksheet.Cells[row, col].Value = user.Active ? "是" : "否";
                    col++;

                    row++;
                }
                xlPackage.Workbook.Properties.Title = string.Format("{0} 用户列表", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Author = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.Subject = string.Format("{0} 用户列表", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Keywords = string.Format("{0} 用户列表", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Category = "Users";
                xlPackage.Workbook.Properties.Comments = "优社电商技术支持";

                xlPackage.Workbook.Properties.Company = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.HyperlinkBase = new Uri(_storeInformationSettings.StoreUrl);

                xlPackage.Save();
            }
        }

        protected virtual string GetPictures(int pictureId)
        {
            var picture = _pictureService.GetPictureById(pictureId);
            return _pictureService.GetThumbLocalPath(picture);
        }
        protected virtual byte[] ExportToXlsx<T>(PropertyByName<T>[] properties, IEnumerable<T> itemsToExport)
        {
            using (var stream = new MemoryStream())
            {
                using (var xlPackage = new ExcelPackage(stream))
                {

                    var worksheet = xlPackage.Workbook.Worksheets.Add(typeof(T).Name);

                    var manager = new PropertyManager<T>(properties.Where(p => !p.Ignore).ToArray());
                    manager.WriteCaption(worksheet, SetCaptionStyle);

                    var row = 2;
                    foreach (var items in itemsToExport)
                    {
                        manager.CurrentObject = items;
                        manager.WriteToXlsx(worksheet, row++);
                    }

                    xlPackage.Save();
                }
                return stream.ToArray();
            }
        }

        protected virtual void SetCaptionStyle(ExcelStyle style)
        {
            style.Fill.PatternType = ExcelFillStyle.Solid;
            style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
            style.Font.Bold = true;
        }

        public virtual void ExportAgentBonusToXlsx(Stream stream, IList<AgentBonus> list, User agent)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            // ok, we can run the real code of the sample now
            using (var xlPackage = new ExcelPackage(stream))
            {
                // uncomment this line if you want the XML written out to the outputDir
                //xlPackage.DebugMode = true; 

                // get handle to the existing worksheet
                var worksheet = xlPackage.Workbook.Worksheets.Add("Customers");
                //Create Headers and format them
                var properties = new string[]
                {
                    "订单编号",
                    "订单金额",
                    "用户",
                    "代理用户",
                    "代理类型",
                    "佣金",
                    "是否提现",
                    "是否有效",
                    "创建时间"
                };
                for (int i = 0; i < properties.Length; i++)
                {
                    worksheet.Cells[1, i + 1].Value = properties[i];
                    worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
                    worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
                    worksheet.Cells[1, i + 1].Style.Font.Bold = true;
                }

                int row = 2;
                foreach (var bonus in list)
                {
                    int col = 1;

                    var order = _orderService.GetOrderById(bonus.OrderId);
                    if (order == null) continue;

                    var user = _userService.GetUserById(bonus.UserId);
                    if (user == null) continue;

                    worksheet.Cells[row, col].Value = order.Code;
                    col++;

                    worksheet.Cells[row, col].Value = PriceFormatter.FormatPrice(order.OrderTotal);
                    col++;

                    worksheet.Cells[row, col].Value = string.Format("{0}-{1}", user.Nickname, user.PhoneNumber);
                    col++;

                    worksheet.Cells[row, col].Value = string.Format("{0}-{1}", agent.Id, agent.Nickname);
                    col++;

                    worksheet.Cells[row, col].Value = bonus.AgentId == agent.Id ? "一级分红" : "二级分红";
                    col++;

                    worksheet.Cells[row, col].Value = bonus.AgentId == agent.Id ? bonus.Price : bonus.ParentFee;
                    col++;

                    worksheet.Cells[row, col].Value = bonus.Cash ? "是" : "否";
                    col++;

                    worksheet.Cells[row, col].Value = bonus.IsValid ? "是" : "否";
                    col++;

                    worksheet.Cells[row, col].Value = bonus.CreateTime.ToString("yyyy-MM-dd HH:mm");
                    col++;

                    row++;
                }
                // set some core property values
                xlPackage.Workbook.Properties.Title = string.Format("{0} 分红列表", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Author = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.Subject = string.Format("{0} 分红列表", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Keywords = string.Format("{0} 分红列表", _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Category = "Customers";
                xlPackage.Workbook.Properties.Comments = "优社电商技术支持";

                // set some extended property values
                xlPackage.Workbook.Properties.Company = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.HyperlinkBase = new Uri(_storeInformationSettings.StoreUrl);

                // save the new spreadsheet
                xlPackage.Save();
            }
        }


        public virtual void ExportAgentsToXlsx(Stream stream, IList<User> users)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            using (var xlPackage = new ExcelPackage(stream))
            {
                //xlPackage.DebugMode = true; 

                var worksheet = xlPackage.Workbook.Worksheets.Add("Orders");
                //Create Headers and format them
                var properties = new string[]
                    {
                        "姓名",
                        "昵称",
                        "手机号",
                        "已审核",
                        "下级数量",
                        "总订单数",
                        "生效订单数",
                        "总订单金额",
                        "生效订单金额",
                        "总佣金",
                        "生效佣金",
                        "未生效佣金",
                        "已提现佣金",
                        "未提现佣金",
                        "最近活跃",
                        "创建时间",
                    };
                for (int i = 0; i < properties.Length; i++)
                {
                    worksheet.Cells[1, i + 1].Value = properties[i];
                    worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
                    worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
                    worksheet.Cells[1, i + 1].Style.Font.Bold = true;
                }

                int row = 2;
                foreach (var user in users)
                {
                    int col = 1;

                    worksheet.Cells[row, col].Value = user.Realname;
                    col++;
                    worksheet.Cells[row, col].Value = user.Nickname;
                    col++;
                    worksheet.Cells[row, col].Value = user.PhoneNumber;
                    col++;
                    worksheet.Cells[row, col].Value = user.Approved ? "是" : "否";
                    col++;

                    var summary = _agentService.GetAgentUserSummary(user.Id);

                    worksheet.Cells[row, col].Value = summary.NumberOfAgent;
                    col++;
                    worksheet.Cells[row, col].Value = summary.NumberOfOrder;
                    col++;
                    worksheet.Cells[row, col].Value = summary.NumberOfValidOrder;
                    col++;
                    worksheet.Cells[row, col].Value = summary.AmountOfOrder;
                    col++;
                    worksheet.Cells[row, col].Value = summary.AmountOfValidOrder;
                    col++;
                    worksheet.Cells[row, col].Value = summary.TotalAmountOfFee;
                    col++;
                    worksheet.Cells[row, col].Value = summary.AmountOfValidFee;
                    col++;
                    worksheet.Cells[row, col].Value = summary.AmountOfNoValidFee;
                    col++;
                    worksheet.Cells[row, col].Value = summary.CashFee;
                    col++;
                    worksheet.Cells[row, col].Value = summary.NoCashFee;
                    col++;


                    worksheet.Cells[row, col].Value = user.LastActivityTime.ToString("yyyy-MM-dd HH:mm");
                    col++;
                    worksheet.Cells[row, col].Value = user.CreateTime.ToString("yyyy-MM-dd HH:mm");
                    col++;

                    //next row
                    row++;
                }
                // set some core property values
                xlPackage.Workbook.Properties.Title = string.Format("{0} {1} 订单", DateTime.Now.ToString("yyMMddHHmm"), _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Author = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.Subject = string.Format("{0} {1} 订单", DateTime.Now.ToString("yyMMddHHmm"), _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Keywords = string.Format("{0} {1} 订单", DateTime.Now.ToString("yyMMddHHmm"), _storeInformationSettings.StoreName);
                xlPackage.Workbook.Properties.Category = "Orders";
                xlPackage.Workbook.Properties.Comments = "优社电商技术支持";

                // set some extended property values
                xlPackage.Workbook.Properties.Company = _storeInformationSettings.StoreName;
                xlPackage.Workbook.Properties.HyperlinkBase = new Uri(_storeInformationSettings.StoreUrl);

                // save the new spreadsheet
                xlPackage.Save();
            }
        }
        #endregion
    }
}
